unit FrmPrincipal;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, StdCtrls,
  Grids, ComCtrls, Menus, LCLType, Process, clases, Clipbrd, ExtCtrls,
  ClaseCodificador, frmacerca, globaldatos;

type

  { TFrmMain }

  TFrmMain = class(TForm)
    ARadioSinAudio: TRadioButton;
    BtnAcercaDe: TButton;
    BtnAss: TButton;
    BtnConvertir: TButton;
    BtnMkv: TButton;
    BtnMp4: TButton;
    BtnReset: TButton;
    BtnSalir: TButton;
    CheckPredeterminado: TCheckBox;
    CheckSubtitulo: TCheckBox;
    ChkBoxPasadas: TCheckBox;
    ComboAudio: TComboBox;
    ComboSubtitulo: TComboBox;
    ComboVelocidad: TComboBox;
    GroupArchivos: TGroupBox;
    GroupAudio: TGroupBox;
    GroupCodec: TGroupBox;
    GroupMensajes: TGroupBox;
    GroupPistas: TGroupBox;
    GroupSalida: TGroupBox;
    GroupVideo: TGroupBox;
    Label1: TLabel;
    Label10: TLabel;
    Label11: TLabel;
    Label12: TLabel;
    Label13: TLabel;
    Label2: TLabel;
    Label9: TLabel;
    MemoMensajes: TMemo;
    MenuItem1: TMenuItem;
    MenuLog: TMenuItem;
    OpenDialogAss: TOpenDialog;
    OpenDialogMkv: TOpenDialog;
    Paginas: TPageControl;
    PopupMensajes: TPopupMenu;
    VRadioHD: TRadioButton;
    VRadioSD: TRadioButton;
    VRadioPersonalizado: TRadioButton;
    ARadioHD: TRadioButton;
    ARadioSD: TRadioButton;
    ARadioPersonalizado: TRadioButton;
    SaveDialogMp4: TSaveDialog;
    BarraEstado: TStatusBar;
    TabGeneral: TTabSheet;
    TabAvanzado: TTabSheet;
    TxtAss: TEdit;
    TxtAudioBitrate: TEdit;
    TxtMkv: TEdit;
    TxtMp4: TEdit;
    TxtVideoBitrate: TEdit;
    procedure ARadioHDChange(Sender: TObject);
    procedure ARadioPersonalizadoChange(Sender: TObject);
    procedure ARadioSDChange(Sender: TObject);
    procedure ARadioSinAudioChange(Sender: TObject);
    procedure BtnAcercaDeClick(Sender: TObject);
    procedure BtnConvertirClick(Sender: TObject);
    procedure BtnMkvClick(Sender: TObject);
    procedure AgregarArchivoMkv(a : TFileName);
    procedure AgregarArchivoAss(a : String);
    procedure AgregarArchivoMp4(a : String);
    procedure BtnAssClick(Sender: TObject);
    procedure BtnMp4Click(Sender: TObject);
    procedure BtnResetClick(Sender: TObject);
    procedure BtnSalirClick(Sender: TObject);
    procedure CheckPredeterminadoChange(Sender: TObject);
    procedure CheckSubtituloChange(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormShow(Sender: TObject);
    procedure Estado(mens : String = 'esperando.'; salida : Boolean = false);
    procedure Mensaje(mensaje : String = '');
    procedure AgregarPistas();
    procedure MenuItem1Click(Sender: TObject);
    function IsStrANumber(const S: string): Boolean;
    procedure EstadoProcesoTrabajo();
    procedure VRadioHDChange(Sender: TObject);
    procedure VRadioPersonalizadoChange(Sender: TObject);
    procedure TabControl1Change(Sender: TObject);
    procedure TxtMkvChange(Sender: TObject);
    function VerificarAvance(): Boolean;
    procedure EstadoControles(E: Boolean);
    procedure Respira;
    Procedure Version;
    function CrearLog: Boolean;
    procedure VRadioSDChange(Sender: TObject);
//    procedure AgregarSubs();
  private
    { private declarations }
  public
    { public declarations }
  end; 

var
  FrmMain: TFrmMain;
  CargadoAss, CargadoMkv : Boolean;
  // En TDatosMkv se guardarán los resultados de la salida de consola
  TDatosMkv : TStringList;
  TPistasMkv : TStringList;
  TSalidaAVS : TStringList;
  TContenedorAbierto : TContenedor;
  NumeroPistasAudio : Integer = 0;
  NumeroPistasVideo : Integer = 0;
  NumeroPistasSubtitulo : Integer = 0;
  Trabajo : TCodificador;
  Trabajando : Boolean;

implementation
uses utils;

{$R *.lfm}

{ TFrmMain }
function TFrmMain.CrearLog: Boolean;
Begin
  Result := MenuLog.Checked;
end;

procedure TFrmMain.VRadioSDChange(Sender: TObject);
begin
    TxtVideoBitrate.Text := '380';
    TxtVideoBitrate.ReadOnly := True;
    TxtVideoBitRate.Color := $00F7F7F7;

end;

procedure TFrmMain.Version;
Begin
  MemoMensajes.Lines.Clear;
  MemoMensajes.Lines.Add('AnimeManiac '+ GetVersion + ' (Por ManiacPC)');
end;

procedure TFrmMain.Respira;
Begin
  Application.ProcessMessages;
  Sleep(1500);
  Application.ProcessMessages;
end;

procedure TFrmMain.EstadoControles(E: Boolean);
Begin
  GroupArchivos.Enabled := E;
  GroupVideo.Enabled := E;
  GroupAudio.Enabled := E;
  GroupCodec.Enabled := E;
  GroupPistas.Enabled := E;
  GroupSalida.Enabled := E;

end;

function TFrmMain.VerificarAvance(): Boolean;
Begin
  Result := Trabajando;
end;

procedure TFrmMain.EstadoProcesoTrabajo();
Begin
  While (Trabajo.ObtenerEstadoProceso) Do Begin
    Estado(Trabajo.ObtenerEstado());
    Application.ProcessMessages;
    Sleep(25);
    Application.ProcessMessages;

  end;
end;

procedure TFrmMain.VRadioHDChange(Sender: TObject);
begin
    TxtVideoBitrate.Text := '1000';
    TxtVideoBitrate.ReadOnly := True;
    TxtVideoBitRate.Color := $00F7F7F7;
end;

procedure TFrmMain.VRadioPersonalizadoChange(Sender: TObject);
begin
    TxtVideoBitrate.ReadOnly := False;
    TxtVideoBitRate.Color := clWhite;
    TxtVideoBitRate.SetFocus;
end;

procedure TFrmMain.TabControl1Change(Sender: TObject);
begin

end;

procedure TFrmMain.TxtMkvChange(Sender: TObject);
begin

end;

function TFrmMain.IsStrANumber(const S: string): Boolean;
var
  P: PChar;
begin
  P      := PChar(S);
  Result := False;
  while P^ <> #0 do
  begin
    if not (P^ in ['0'..'9']) then Exit;
    Inc(P);
  end;
  Result := True;
end;

procedure TFrmMain.AgregarPistas();
Var
  i : Integer;
  Cadena : String;
Begin

  ComboAudio.Items.Clear;
  ComboSubtitulo.Items.Clear;

  // Clase contenedor
  With TContenedorAbierto Do
  Begin
    For i := 0 To TotalPistas - 1 Do Begin
      //ShowMessage(Tipo[i]);
      // Si la pista es del tipo video...
      If Tipo[i] = 'video' Then
        NumeroPistasVideo := NumeroPistasVideo + 1;

      // Si la pista es del tipo audio...
      If Tipo[i] = 'audio' Then begin
        NumeroPistasAudio := NumeroPistasAudio + 1;
        Cadena := '';

        // Numero de pista
        If Pista[i] < 10 then Cadena := '0'+IntToStr(Pista[i])+' | '
        Else Cadena := IntToStr(Pista[i])+' | ';

        // Pista Predeterminada
        If (Predeterminado[i]) Then Cadena := Cadena + ' PRED: NO | '
        else Cadena := Cadena + ' PRED: SI | ';

        // Codec utilizado
        Cadena := Cadena + ' [C:'+Codec[i]+'] | ';

        // Frecuencia y canales
        Cadena := Cadena + ' (F:'+IntToStr(Frecuencia[i])+',CH:'+IntToStr(Canales[i])+') | ';

        // Lenguaje
        Cadena := Cadena + ' L: ' + Lenguaje[i];

        // Guardamos en otro array el tipo de codec de audio
        TipoCodecAudio[NumeroPistasAudio - 1] := Codec[i];

        // Agregamos al combobox
        ComboAudio.Items.Add(Cadena);
        ComboAudio.ItemIndex := 0;
      end;
      // Si la pista es del tipo subtitulos...
      If Tipo[i] = 'subtitles' Then begin
        NumeroPistasSubtitulo := NumeroPistasSubtitulo + 1;
        Cadena := '';

        // Numero de pista
        If Pista[i] < 10 then Cadena := '0'+IntToStr(Pista[i])+' | '
        Else Cadena := IntToStr(Pista[i])+' | ';

        // Pista Predeterminada
        If (Predeterminado[i]) Then Cadena := Cadena + ' PRED: NO | '
        else Cadena := Cadena + ' PRED: SI | ';

        // Codec utilizado
        Cadena := Cadena + ' [C:'+Codec[i]+'] | ';

        // Lenguaje
        Cadena := Cadena + ' L: ' + Lenguaje[i];

        // Agregamos al combobox
        ComboSubtitulo.Items.Add(Cadena);
        ComboSubtitulo.ItemIndex := 0;
      end;
    end;
  end;

  // Si no encontramos pistas, agregamos un vacío
  ComboSubtitulo.Items.Add('(ninguno)');
  ComboSubtitulo.ItemIndex := 0;

  ComboAudio.Items.Add('(ninguno)');
  ComboAudio.ItemIndex := 0;

end;

procedure TFrmMain.MenuItem1Click(Sender: TObject);
begin
  Version;
end;

procedure TFrmMain.Estado(mens : String; salida : boolean);
Begin
     BarraEstado.Panels[1].Text := mens;
     If (Salida) then
        Mensaje(mens);
end;

procedure TFrmMain.Mensaje(mensaje : String = '');
Begin
  MemoMensajes.Lines.Add('['+TimeToStr(Time) + '] ' + mensaje);
end;

procedure TFrmMain.AgregarArchivoMp4(a : String);
Begin
  If AnsiLowerCase(RightStr(a, 4)) <> '.mp4' Then
     TxtMp4.Text := a + '.mp4'
  else
    TxtMp4.Text := a;
end;

procedure TFrmMain.AgregarArchivoAss(a : String);
Begin
   TxtAss.Text := a;
end;

procedure TFrmMain.BtnAssClick(Sender: TObject);
begin
  If OpenDialogAss.Execute Then
        AgregarArchivoAss(OpenDialogAss.Files[0]);
end;

procedure TFrmMain.BtnMp4Click(Sender: TObject);
begin
  If SaveDialogMp4.Execute then
     AgregarArchivoMp4(SaveDialogMp4.Files[0]);
end;

procedure TFrmMain.BtnResetClick(Sender: TObject);
begin
  If (Sender <> BtnConvertir) Then begin
     If ((Application.MessageBox('¿Está seguro de detener los trabajos?', 'Pregunta',
     MB_ICONQUESTION+MB_YESNO)) = ID_YES) Then Begin
       If (Trabajo.ObtenerEstadoProceso) Then Trabajo.Matar;
       Trabajando := False;
       BtnConvertir.Enabled := True;
       BtnReset.Enabled := False;
       Estado('Cancelado');
       Mensaje('* Trabajo cancelado...');
       { LOG } If CrearLog Then
      { LOG }    GenerarLog('Trabajo cancelado...');
       EstadoControles(True);
     end;
  end
  else begin
    Trabajando := False;
    BtnConvertir.Enabled := True;
    BtnReset.Enabled := False;
    Estado('Hecho');
    Mensaje('* Trabajo finalizado...');
    EstadoControles(True);
  end;

end;

procedure TFrmMain.BtnSalirClick(Sender: TObject);
begin
  Close;
end;

procedure TFrmMain.CheckPredeterminadoChange(Sender: TObject);
begin
  If Not (CheckPredeterminado.Checked) Then Begin
       TxtMp4.Color := clDefault;
       BtnMp4.Enabled := True;
    end
    else begin
      TxtMp4.Color := $00F7F7F7;
      BtnMp4.Enabled := False;
    end;
end;

procedure TFrmMain.CheckSubtituloChange(Sender: TObject);
begin
  If Not (CheckSubtitulo.Checked) Then Begin
     TxtAss.Color := clDefault;
     BtnAss.Enabled := True;
  end
  else begin
    TxtAss.Color := $00F7F7F7;
    BtnAss.Enabled := False;
  end;

end;

procedure TFrmMain.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  If (Application.MessageBox('¿Realmente desea salir?', 'Pregunta',
           MB_ICONQUESTION+MB_YESNO))= ID_NO Then CloseAction := caNone;
end;

procedure TFrmMain.FormShow(Sender: TObject);
var
  LogPrograma : TFileName;
begin
  SetVersion();
  Version;
  // Indicadores para saber si se cargaron los
  // archivos
  CargadoMkv := False;
  CargadoAss := False;

  TDatosMkv := TStringList.Create;
  TContenedorAbierto := TContenedor.Create;
  TPistasMkv := TStringList.Create;
  TSalidaAVS := TStringList.Create;
  Trabajo.Create();
  Trabajando := False;

  Application.MessageBox('Este programa se encuentra en una versión BETA, ' +
      'donde las funcionalidades requieren de muchos arreglos y ayuda en la ' +
      'correción de errores y retroalimentación por parte de los usuarios que ' +
      'lo utilicen. No está apto para la producción de videos. Cualquier ' +
      'error que pueda encontrarse, por favor registrarlo (si es que pueden ' +
      'con el mayor detalle posible) en la sección "Issues" de la página web ' +
      'del proyecto (más información en la ventana "Acerca de.."). Muchas gracias',
      '¡IMPORTANTE!', MB_ICONEXCLAMATION);

  LogPrograma := ExtractFilePath(Application.ExeName) + '\logs\programa.log';

  If FileExistsUTF8(LogPrograma) Then DeleteFileUTF8(LogPrograma);
  VerificarRequeridos;

  VerificarSistema;
//  If Get64Bits Then ChkBox64Bits.Checked := True
 // Else ChkBox64Bits.Enabled := False;

end;

procedure TFrmMain.AgregarArchivoMkv(a : TFileName);
var
  Temporal, Completo : String;
  Ruta : String;
  DirectorioPrograma : String;
  Busqueda : TSearchRec;

Begin
     // Limpieza en caso de cargar otro archivo
     TDatosMkv.Clear;
     TPistasMkv.Clear;
     TContenedorAbierto.VaciarArrays();
     NumeroPistasAudio := 0;
     NumeroPistasSubtitulo := 0;
     NumeroPistasVideo := 0;

//     FindFirstUTF8(a, faAnyFile, Busqueda);
//     Ruta := ExtractFilePath(a) + StrPas(Busqueda.FindData.cAlternateFileName);
//     FindCloseUTF8(Busqueda);
     Ruta := a;
     TxtMkv.Text := Ruta;

     DirectorioPrograma := ExtractFilePath(Application.ExeName);

     // Verifica si existe el archivo
     // y si no existe se sale del procedimiento
     if not FileExistsUTF8(Ruta) then begin
       Estado('Error al abrir el archivo.');
       Application.MessageBox('No existe el archivo.', 'Error', MB_ICONERROR);
       Exit;
     end;

     Estado('Ejecutando mkvinfo...');
     Mensaje('* Ejecutando mkvinfo...');

     //EjecucionConsola(DirectorioPrograma +'\tools\mkvtool\mkvinfo.exe', '"'+Ruta+'"', TDatosMkv);
     // Generamos log (si está tickeado)
     { LOG } If CrearLog Then
     { LOG }    GenerarLog(DirectorioPrograma +'tools\mkvtool\mkvinfo.exe + "'+Ruta+'" /// + TDatosMkv');

     // Generamos log (si está tickeado)
     If (EjecucionConsolaInfo(DirectorioPrograma +'tools\mkvtool\mkvinfo.exe',
                             '"'+Ruta+'"', TDatosMkv) <> 0)
         And (CrearLog) Then begin
            { LOG } GenerarLog('mkvinfo: Salida error');
            Estado('Error al ejecutar MKVINFO.', True);
        end;
//     Clipboard.AsText := DirectorioPrograma +'tools\mkvtool\mkvinfo.exe' + '"'+Ruta+'"';
     // Primera verificación, ver si el archivo elegido es válido
     // y además si contiene una pista de video (minimo)
     If MkvValido(TDatosMkv) Then Begin
        Estado('* Analizando resultado (.mkv)...', True);
        // En base a búsqueda, desglozamos cuántas pistas hay
        Try
           TPistasMkv := ObtenerPistasMkv(TDatosMkv);
           TContenedorAbierto.DesglozarPistas(TDatosMkv, TPistasMkv, TPistasMkv.Count);
           AgregarPistas();
           Estado('Análisis completo.');
           Mensaje('+ Análisis completo.');
           Mensaje('+ Encontradas ' + IntToStr(NumeroPistasVideo) + ' pistas de video, ' + IntToStr(NumeroPistasAudio) + ' pistas de audio, y ' + IntToStr(NumeroPistasSubtitulo) + ' pistas de subtitulos.');
        Except
           Mensaje('- Error al efectuar el análisis, por favor reintentelo');
           { LOG }  If CrearLog Then GenerarLog('Error en analizar: MkvValido');
           Estado('Error');
        end;
//        AgregarSubs();
     end else
     begin
       Estado('Error al abrir archivo. (no es válido o no contiene pista de video)', true);
       { LOG } If CrearLog Then GenerarLog('Error al abrir el archivo');
     end;

     // Si está marcado el checkbox "Mismo nombre y carpeta"
     If CheckPredeterminado.Checked Then begin
        // Cortamos la extensión .MKV
        Temporal := LeftStr(a, Length(a)-4);
        // Si ya existe el archivo con ese nombre, agregamos (1)
        // Sucesivamente antes del .mp4
        While (FileExistsUTF8(Temporal + '.mp4')) Do
        Begin
          Temporal := Temporal + '(1)';
        end;
        // Completamos la cadena de texto
        Completo := Temporal + '.mp4';
        TxtMp4.Text := Completo;
     end;
end;

procedure TFrmMain.BtnMkvClick(Sender: TObject);
begin
  If OpenDialogMkv.Execute Then
      AgregarArchivoMkv(OpenDialogMkv.FileName);
end;

procedure TFrmMain.BtnConvertirClick(Sender: TObject);
var
  Subtitulo : TFileName;
  Audio : TFileName;
  Original : TFileName;
  TSalida : TStringList;
  DirectorioPrograma : String;
  CadenaMkvExtract, ParametrosMkvExtract : String;
  TemporalAudio : String;
  TemporalAudioExtension : String;
  Bitrate : Integer;
  ExisteAudio : Boolean = False;
  Mp4Temporal : String;
  Salida : String;
  Archivo : TextFile;
begin
  Original := TxtMkv.Text;
  Subtitulo := TxtAss.Text;
  Salida := TxtMp4.Text;
  TSalida := TStringList.Create;
  Trabajando := True;

  Trabajo := TCodificador.Create();

  DirectorioPrograma := ExtractFilePath(Application.ExeName);

  If FileExistsUTF8(Salida) Then begin
    { LOG } If CrearLog Then GenerarLog('<output>: Ya existe el fichero de salida: "'+Salida+'"');
     If (Application.MessageBox('El archivo de salida ya existe, ¿Desea reemplazarlo?',
        'Pregunta', MB_ICONQUESTION+MB_YESNO)) = ID_NO Then Exit;
  end;

  // Verificamos si todavía existe el MKV
  If Not FileExistsUTF8(Original) Then Begin
    { LOG } If CrearLog Then GenerarLog('<input>: No existe el archivo mkv: "'+Original+'"');
    Estado('Error al abrir el archivo mkv');
    Mensaje('- Archivo mkv no existe');
    Exit;
  end
  else begin
    Estado('* Convirtiendo...');
    Mensaje('===COMENZANDO CONVERSION===');
    { LOG } If CrearLog Then GenerarLog('start: ===Comienza la conversión===');
    { LOG } If CrearLog Then GenerarLog('<input>: no existe el archivo, se crea uno nuevo');
    BtnConvertir.Enabled := False;
    BtnReset.Enabled := True;
    EstadoControles(False);
    Application.ProcessMessages;
    If (Trabajo.ObtenerEstadoProceso) Then Trabajo.Matar;
  end;

  Subtitulo := TxtAss.Text;
  // ************ SUBTITULOS ************
  Mensaje('* Extrayendo y procesando subtítulos...');
  // Si está checkeado el "subtitulo dentro del mkv"
  If (CheckSubtitulo.Checked) Then begin
     { LOG } If CrearLog then GenerarLog('<gui>: Se busca una pista de subs en video');
     // Si es que existe una pista de subtitulos
     If ((ComboSubtitulo.Items.Count > 0) And (ComboSubtitulo.Items[0] <> '(ninguno)')) Then Begin
        // Creamos los comandos para mkvextract
        CadenaMkvExtract := DirectorioPrograma + 'tools\mkvtool\mkvextract.exe';
        ParametrosMkvExtract := 'tracks "'+Original+'" '+
                             IntToStr(StrToInt(LeftStr(ComboSubtitulo.Items[ComboSubtitulo.ItemIndex],2)))
                             +':"'+DirectorioPrograma+'temp\subs.ass"';
        { LOG } If CrearLog Then GenerarLog('mkvextract.exe: (subs) ' + CadenaMkvExtract + ' ' + ParametrosMkvExtract);
        // Ejecutamos mkvextract para la pista de subtitulos
        Trabajo.Ejecutar(CadenaMkvExtract, ParametrosMkvExtract);
        EstadoProcesoTrabajo();
        // Verificamos si no se detuvo
        If Not VerificarAvance() Then Exit;
        Respira;
        { LOG } If CrearLog Then GenerarLog('mkvextract.exe: salida ' + IntToStr(Trabajo.GetCodigoSalida));
        { CODIGO ERROR }
        {E} If (Trabajo.GetCodigoSalida <> 0) then begin
        {E}    If CrearLog Then GenerarLog('<mensaje_error>: ' + Trabajo.ObtenerEstado());
        {E}    Application.MessageBox('Error al extraer pistas .ass', 'Error', MB_ICONWARNING);
        {E}    Estado('Error al extraer pistas .ass');
        {E}    Mensaje('* Error (mkvextract), abortando...');
        {E}    Exit;
        {E} end;
        { / CODIGO ERROR }


        { LOG } If CrearLog Then GenerarLog('perfil.avs: "' + Original + '", "' + DirectorioPrograma+'temp\subs.ass"');
        // Creamos el script AviSynth
        GenerarAVS(Original, DirectorioPrograma+'temp\subs.ass');
        { LOG } If CrearLog Then GenerarLog('perfil.avs: generado');
        Mensaje('+ Archivo AviSynth (.avs) generado');
     end
     else begin // Si no se encuentran pistas, no se agregan
       Mensaje('- No se han encontrado subtitulos (.ass)');
       { LOG } If CrearLog Then GenerarLog('perfil.avs: No se encontraron pistas de subs en el mkv, se generará perfil.avs sin subs');
       // Creamos el script AviSynth
       GenerarAVS(Original);
       Mensaje('+ Archivo AviSynth (.avs) generado');
       { LOG } If CrearLog Then GenerarLog('perfil.avs: generado');
     end;
  end
  else begin
    // Si es que el subtitulo ass va separado verificamos que exista
    If FileExistsUTF8(Subtitulo) Then Begin
       { LOG } If CrearLog Then begin
          { LOG } GenerarLog('.ass: por separado');
          { LOG } GenerarLog('.ass: "'+Original+'", "'+Subtitulo+'"');
       { LOG } end;

       // Creamos el script AviSynth
       GenerarAVS(Original, Subtitulo);
       Mensaje('+ Archivo AviSynth Script (.avs) generado');
       { LOG } If CrearLog Then GenerarLog('perfil.avs: generado');
    end
    Else Begin
      { LOG } If CrearLog Then GenerarLog('.ass: no existe archivo de subtitulo por separado');
      Mensaje('- No existe archivo de subtitulo (.ass)');
      Exit;
    end;
  end;

  // ************ AUDIO ************
  Mensaje('* Extrayendo audio...');
  TemporalAudio := DirectorioPrograma+'temp\audio.'+ObtenerExtension(TContenedorAbierto.TipoCodecAudio[ComboAudio.ItemIndex]);
  TemporalAudioExtension := ObtenerExtension(TContenedorAbierto.TipoCodecAudio[ComboAudio.ItemIndex]);
  // Si es que existe una pista de audio
  If ((ComboAudio.Items.Count > 0) And (ComboAudio.Items[ComboAudio.ItemIndex] <> '(ninguno)')) Then Begin
     // Creamos los comandos para mkvextract
     CadenaMkvExtract := DirectorioPrograma + 'tools\mkvtool\mkvextract.exe';
     ParametrosMkvExtract := 'tracks "'+Original+'" '+
                          IntToStr(StrToInt(LeftStr(ComboAudio.Items[ComboAudio.ItemIndex],2)))
                          +':"'+TemporalAudio+'"';
     { LOG } If CrearLog Then GenerarLog('audio.'+TemporalAudioExtension+': ' + CadenaMkvExtract + ' ' + ParametrosMkvExtract);
     // Ejecutamos mkvextract para la pista de subtitulos
     Trabajo.Ejecutar(CadenaMkvExtract, ParametrosMkvExtract);
     EstadoProcesoTrabajo();
     // Verificamos si no se detuvo
     If Not VerificarAvance() Then Exit;
     Respira;
     { LOG } If CrearLog Then GenerarLog('mkvextract.exe: salida ' + IntToStr(Trabajo.GetCodigoSalida));
     { CODIGO ERROR }
     {E} If (Trabajo.GetCodigoSalida <> 0) then begin
     {E}    If CrearLog Then GenerarLog('<mensaje_error>: ' + Trabajo.ObtenerEstado());
     {E}    Application.MessageBox(PChar('Error al extraer pista(s) .'+TemporalAudioExtension), 'Error', MB_ICONWARNING);
     {E}    Estado('Error al extraer pista(s) .'+TemporalAudioExtension);
     {E}    Mensaje('* Error (mkvextract), abortando...');
     {E}    Exit;
     {E} end;
     { / CODIGO ERROR }


     Mensaje('+ Archivo de audio (.'+TemporalAudioExtension+') generado');
     { LOG } If CrearLog Then GenerarLog('audio.aac: generado');

     // Convirtiendo a wav
     { LOG } If CrearLog Then GenerarLog('audio.wav: creando...');
     Mensaje('* Convirtiendo audio a wav (1/2)...');
     If (TemporalAudioExtension = 'aac') Then Begin
         CadenaMkvExtract := DirectorioPrograma + 'tools\faad\faad.exe';
         ParametrosMkvExtract := '-o "' + DirectorioPrograma + 'temp\audio.wav" ' + '"' + DirectorioPrograma + 'temp\audio.aac"';
     End Else Begin
         CadenaMkvExtract := DirectorioPrograma + 'tools\sox\sox.exe';
         ParametrosMkvExtract := '-V "' + TemporalAudio + '" "' + DirectorioPrograma + 'temp\audio.wav"';
     End;
     { LOG } If CrearLog Then GenerarLog('audio.wav: ' + CadenaMkvExtract + ' ' + ParametrosMkvExtract);
     //ShowMessage(ParametrosMkvExtract);
     Trabajo.Ejecutar(CadenaMkvExtract, ParametrosMkvExtract);
     EstadoProcesoTrabajo();
     // Verificamos si no se detuvo
     If Not VerificarAvance() Then Exit;
     Respira;
     { LOG } If CrearLog Then GenerarLog('sox.exe: salida ' + IntToStr(Trabajo.GetCodigoSalida));
     { CODIGO ERROR }
     {E} If (Trabajo.GetCodigoSalida <> 0) then begin
     {E}    If CrearLog Then GenerarLog('<mensaje_error>: ' + Trabajo.ObtenerEstado());
     {E}    Application.MessageBox(PChar('Error al convertir .'+TemporalAudioExtension), 'Error', MB_ICONWARNING);
     {E}    Estado('Error al convertir .'+TemporalAudioExtension);
     {E}    Mensaje('* Error (sox), abortando...');
     {E}    Exit;
     {E} end;
     { / CODIGO ERROR }


     // Convirtiendo a m4a
     { LOG } If CrearLog Then GenerarLog('audio.m4a: Creando..');
     Mensaje('* Convirtiendo audio a m4a (2/2)...');
     If (IsStrANumber(TxtAudioBitrate.Text)) Then Begin
        If (StrToInt(TxtAudioBitrate.Text) < 100) Then Begin
           Bitrate := StrToInt(TxtAudioBitrate.Text) * 1000;
           CadenaMkvExtract := DirectorioPrograma + 'tools\neroAacEnc\neroAacEnc.exe';
           ParametrosMkvExtract := '-br ' + IntToStr(Bitrate) + '-2pass -he -if "'
               + DirectorioPrograma + 'temp\audio.wav" ' + ' -of "' + DirectorioPrograma + 'temp\audio.m4a"';
           { LOG } If CrearLog Then GenerarLog('audio.m4a: ' + CadenaMkvExtract + ' ' + ParametrosMkvExtract);
           Trabajo.Ejecutar(CadenaMkvExtract, ParametrosMkvExtract);
           EstadoProcesoTrabajo();
           DeleteFileUTF8(DirectorioPrograma + 'temp\audio.wav');
           // Verificamos si no se detuvo
           If Not VerificarAvance() Then Exit;
           ExisteAudio := True;
           Respira;
           { LOG } If CrearLog Then GenerarLog('neroAacEnc.exe: salida ' + IntToStr(Trabajo.GetCodigoSalida));
        end else begin
          { LOG } If CrearLog Then GenerarLog('audio.m4a: bitrate mayor a 100. (ignorado)');
          Mensaje('- El bitrate de audio no puede ser mayor a 100 (ignorando)');
          ExisteAudio := False;
        end;
     end else begin
       { LOG } If CrearLog Then GenerarLog('audio.m4a: bitrate mal escrito. (ignorado)');
       Mensaje('- El valor del bitrate de audio no es válido (ignorando)');
       ExisteAudio := False;
     end;
  end
  else begin // Si no se encuentran pistas, no se agregan
    { LOG } If CrearLog Then GenerarLog('audio.m4a: **no hay pistas de audio**');
    Mensaje('- No se han encontrado pistas de audio (ignorado)');
  end;

  // ************ VIDEO ************
  //ObtenerVelocidadCodificacion();
  If (IsStrANumber(TxtVideoBitrate.Text)) Then Begin
       If (StrToInt(TxtVideoBitrate.Text) < 1500) Then Begin
          Bitrate := StrToInt(TxtVideoBitrate.Text);

          // Codificación
          Mensaje('* Codificando video...');
          Application.Processmessages;
          If FileExistsUTF8(Salida) Then DeleteFileUTF8(Salida);
          CadenaMkvExtract := DirectorioPrograma + 'tools\x264\x264.exe';
          ParametrosMkvExtract := '--level 4.2 --preset ' + ObtenerVelocidadCodificacion(ComboVelocidad.Items[ComboVelocidad.ItemIndex])
             + ' --tune animation --bitrate ' + IntToStr(Bitrate) + ' --output "' + LeftStr(Salida, Length(Salida)-4) + '_.mp4" "' + DirectorioPrograma+'temp\perfil.avs"';
          { LOG } If CrearLog Then GenerarLog('<video>.mp4: ' + CadenaMkvExtract + ' ' + ParametrosMkvExtract);
          Trabajo.Ejecutar(CadenaMkvExtract, ParametrosMkvExtract);
          EstadoProcesoTrabajo();
          // Verificamos si no se detuvo
          If Not VerificarAvance() Then Exit;
          Respira;
          { LOG } If CrearLog Then GenerarLog('x264.exe: salida ' + IntToStr(Trabajo.GetCodigoSalida));
          { CODIGO ERROR }
          {E} If (Trabajo.GetCodigoSalida <> 0) then begin
          {E}    If CrearLog Then GenerarLog('<mensaje_error>: ' + Trabajo.ObtenerEstado());
          {E}    Application.MessageBox('Error al crear video', 'Error', MB_ICONWARNING);
          {E}    Estado('Error al crear video');
          {E}    Mensaje('* Error (x264), abortando...');
          {E}    Exit;
          {E} end;
          { / CODIGO ERROR }


          Mp4Temporal := LeftStr(Salida, Length(Salida)-4) + '_.mp4';
       end else begin
         { LOG } If CrearLog Then GenerarLog('<video>.mp4: bitrate mayor a 1500 (error)');
         Mensaje('- El bitrate de video no puede ser mayor a 1500');
         Exit;
       end;
    end else begin
      { LOG } If CrearLog Then GenerarLog('neroAacEnc.exe: bitrate incorrecto (ignorado)');
      Mensaje('- El valor del bitrate de audio no es válido');
      Exit;
    end;

    If ExisteAudio Then Begin
       { LOG } If CrearLog Then GenerarLog('<video_pegado>.mp4: existe audio, uniendo... ');
       Mensaje('* Uniendo partes del mp4...');
       CadenaMkvExtract := DirectorioPrograma + 'tools\mp4box\mp4box.exe';
       ParametrosMkvExtract := '-add "' + Mp4Temporal + '"#video -add "' + DirectorioPrograma + 'temp\audio.m4a"#audio "' + TxtMp4.Text + '"';
       { LOG } If CrearLog Then GenerarLog('<video_pegado>.mp4: ' + CadenaMkvExtract + ' ' + ParametrosMkvExtract);
       Trabajo.Ejecutar(CadenaMkvExtract, ParametrosMkvExtract);
       EstadoProcesoTrabajo();
       // Verificamos si no se detuvo
       If Not VerificarAvance() Then Exit;
       Respira;
       { LOG } If CrearLog Then GenerarLog('mp4box.exe: salida ' + IntToStr(Trabajo.GetCodigoSalida));
       { CODIGO ERROR }
       {E} If (Trabajo.GetCodigoSalida <> 0) then begin
       {E}    If CrearLog Then GenerarLog('<mensaje_error>: ' + Trabajo.ObtenerEstado());
       {E}    Application.MessageBox('Error al unir mp4 + m4a', 'Error', MB_ICONWARNING);
       {E}    Estado('Error al unir mp4 + m4a');
       {E}    Mensaje('* Error (mp4box), abortando...');
       {E}    Exit;
       {E} end;
       { / CODIGO ERROR }


    end;


    { LOG } If CrearLog Then GenerarLog('<video_final>.mp4: tarea finalizada');
    Mensaje('+ Trabajo completado...');
    Trabajando := False;

    DeleteFileUTF8(Mp4Temporal);

    //ShowMessage(ParametrosMkvExtract);
    // Clipboard.AsText := ParametrosMkvExtract;

    If (Application.MessageBox('¿Desea borrar los archivos temporales?',
       'Pregunta', MB_ICONQUESTION+MB_YESNO)) = ID_YES Then Begin
          If CrearLog Then GenerarLog('<temporales>: borrando audio.m4a, perfil.avs, subs.ass, audio.aac, *.ffindex, *.mkv.ffindex');
          If FileExistsUTF8(DirectorioPrograma + 'temp\audio.m4a') Then
             DeleteFileUTF8(DirectorioPrograma + 'temp\audio.m4a');
          If FileExistsUTF8(DirectorioPrograma + 'temp\perfil.avs') Then
             DeleteFileUTF8(DirectorioPrograma + 'temp\perfil.avs');
          If FileExistsUTF8(DirectorioPrograma + 'temp\subs.ass') Then
             DeleteFileUTF8(DirectorioPrograma + 'temp\subs.ass');
          If FileExistsUTF8(DirectorioPrograma + 'temp\audio.aac') Then
             DeleteFileUTF8(DirectorioPrograma + 'temp\audio.aac');
          If FileExistsUTF8(LeftStr(Original, Length(Original)-4) + '.ffindex') Then
              DeleteFileUTF8(LeftStr(Original, Length(Original)-4) + '.ffindex');
          If FileExistsUTF8(LeftStr(Original, Length(Original)-4) + '.mkv.ffindex') Then
              DeleteFileUTF8(LeftStr(Original, Length(Original)-4) + '.mkv.ffindex');
       end;
    Application.MessageBox('La conversión ha finalizado', 'Información', MB_OK+MB_ICONINFORMATION);
    { LOG } If CrearLog Then GenerarLog('end: ===Finaliza la conversión===');
    BtnResetClick(BtnConvertir);
  end;

procedure TFrmMain.BtnAcercaDeClick(Sender: TObject);
begin
  FrmAcercaDe.ShowModal;
end;

procedure TFrmMain.ARadioHDChange(Sender: TObject);
begin
    TxtAudioBitrate.Text := '48';
    TxtAudioBitrate.ReadOnly := True;
    TxtAudioBitrate.Color := $00F7F7F7;

end;

procedure TFrmMain.ARadioPersonalizadoChange(Sender: TObject);
begin
    TxtAudioBitrate.ReadOnly := False;
    TxtAudioBitrate.Color := clWhite;
    TxtAudioBitrate.SetFocus;
end;

procedure TFrmMain.ARadioSDChange(Sender: TObject);
begin
    TxtAudioBitrate.Text := '32';
    TxtAudioBitrate.ReadOnly := True;
    TxtAudioBitrate.Color := $00F7F7F7;
end;

procedure TFrmMain.ARadioSinAudioChange(Sender: TObject);
begin
    TxtAudioBitrate.Text := '0';
    TxtAudioBitrate.ReadOnly := True;
    TxtAudioBitrate.Color := $00F7F7F7;
end;

end.

